package com.ted.hole2.config;

import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.persistence.Column;
import javax.persistence.EntityManager;
import javax.persistence.Id;
import javax.persistence.Tuple;
import javax.persistence.TupleElement;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Selection;
import javax.transaction.Transactional;

/**
 * 整合全套 ted JPA
 * 
 * @author Zhang Kangkang
 */
public class HoleService {

    /**
     * 基础服务实现
     *
     * @author Zhang Kangkang
     * @version 1.0.0
     */
    public static class RepositoryImpl<T, ID> implements ServiceRepository<T, ID>, Serializable {

        private static final long serialVersionUID = 1L;
        private Class<T> mainClass;
        private String idName;
        private final EntityManager entityManager;

        public RepositoryImpl(Class<T> domainClass, EntityManager em) {
            this.mainClass = domainClass;
            this.idName = ReflectUtils.getIdName(domainClass);
            this.entityManager = em;
        }

        @Transactional
        public List<T> batchSaveOrUpdate(List<T> entities) {
            try {
                entityManager.getTransaction().begin();
                for (T entity : entities) {
                    this.entityManager.merge(entity);
                }
                this.entityManager.flush();
                return entities;
            } finally {
                entityManager.getTransaction().commit();
            }
        }

        @Transactional
        public T saveOrUpdate(T entity) {
            try {
                entityManager.getTransaction().begin();
                T exist = findByPrimaryKey((Serializable)ReflectUtils.getId(entity));
                if (exist == null) {
                    this.entityManager.persist(entity);
                } else {
                    T saved = EntityBuilder.merge(exist, entity);
                    this.entityManager.merge(saved);
                }

                this.entityManager.flush();
                return entity;
            } finally {
                entityManager.getTransaction().commit();
            }
        }

        @Transactional
        public List<T> batchRemove(Serializable[] idSet) {
            try {
                entityManager.getTransaction().begin();
                List<T> entities = findIn(idSet);
                return batchRemove(entities);
            } finally {
                entityManager.getTransaction().commit();
            }
        }

        @Transactional
        public List<T> batchRemove(List<T> entities) {
            try {
                entityManager.getTransaction().begin();
                for (T entity : entities) {
                    this.entityManager
                        .remove(this.entityManager.contains(entity) ? entity : this.entityManager.merge(entity));
                }
                return entities;
            } finally {
                entityManager.getTransaction().commit();
            }
        }

        @Transactional
        public T remove(T entity) {
            try {
                entityManager.getTransaction().begin();
                this.entityManager
                    .remove(this.entityManager.contains(entity) ? entity : this.entityManager.merge(entity));
                return entity;
            } finally {
                entityManager.getTransaction().commit();
            }
        }

        @Transactional
        public T remove(Serializable id) {
            try {
                entityManager.getTransaction().begin();
                T entity = findByPrimaryKey(id);
                return remove(entity);
            } finally {
                entityManager.getTransaction().commit();
            }
        }

        public T findByPrimaryKey(Serializable id) {
            return this.entityManager.find(this.mainClass, id);
        }

        public <E extends T> T findByCondition(E condition) {
            return newQuery().condition(condition).findOne(this.entityManager);
        }

        public <E extends T> List<T> findList(E condition) {
            return findList(condition, null);
        }

        public <E extends T> List<T> findList(E condition, SortChain sort) {
            QueryBuilder<T> queryBuilder = newQuery();

            if (condition != null) {
                queryBuilder.condition(condition);
            }

            if (sort != null) {
                queryBuilder.sort(sort);
            }

            return queryBuilder.findList(this.entityManager);
        }

        public List<T> findList(SortChain sort) {
            return findList(null, sort);
        }

        public List<T> findIn(Serializable[] data) {
            return newQuery().in(this.idName, CollectionUtils.array2Set(data)).findList(this.entityManager);
        }

        public List<T> findIn(Collection<? extends Serializable> data) {
            return newQuery().in(this.idName, data).findList(this.entityManager);
        }

        public List<T> findIn(QueryFunction<T> field, Collection<Serializable> data) {
            return newQuery().in(field, data).findList(this.entityManager);
        }

        public Page<T> findPage(Page<T> page) {
            return findPage(page, this.mainClass, new TupleQueryBuilder<T>(this.mainClass));
        }

        public <E extends T> Page<T> findPage(Page<T> page, E condition) {
            return findPage(page, condition, null);
        }

        public <E extends T> Page<T> findPage(Page<T> page, E condition, SortChain sort) {

            QueryBuilder<T> queryBuilder = newQuery();

            if (condition != null) {
                queryBuilder.condition(condition);
            }

            if (sort != null) {
                queryBuilder.sort(sort);
            }

            return queryBuilder.findPage(page, this.entityManager);
        }

        public Page<T> findPage(Page<T> page, SortChain sort) {
            return findPage(page, null, sort);
        }

        public Long count(QueryBuilder<T> query) {
            return query.count(this.entityManager);
        }

        public <E extends T> List<E> findList(Class<E> cls, QueryBuilder<T> query) {
            return query.findList(cls, this.entityManager);
        }

        public <E extends T> E findOne(Class<E> cls, QueryBuilder<T> query) {
            return query.findOne(cls, this.entityManager);
        }

        public <E extends T> Page<E> findPage(Page<E> page, Class<E> cls, QueryBuilder<T> query) {
            return query.findPage(page, cls, this.entityManager);
        }

        public List<T> findList(QueryBuilder<T> query) {
            return query.findList(this.entityManager);
        }

        public T findOne(QueryBuilder<T> query) {
            return query.findOne(this.entityManager);
        }

        public Page<T> findPage(Page<T> page, QueryBuilder<T> query) {
            return query.findPage(page, this.entityManager);
        }

        public List<Map<String, Object>> findListToMap(QueryBuilder<T> query) {
            return query.findListToMap(this.entityManager);
        }

        public Map<String, Object> findOneToMap(QueryBuilder<T> query) {
            return query.findOneToMap(this.entityManager);
        }

        public Page<Map<String, Object>> findPageToMap(Page<Map<String, Object>> page, QueryBuilder<T> query) {
            return query.findPageToMap(page, this.entityManager);
        }

        public QueryBuilder<T> newQuery() {
            return new TupleQueryBuilder<T>(this.mainClass);
        }

        @Override
        public Class<T> getMainClass() {
            return this.mainClass;
        }

        @Override
        public T executeOneNamedQuery(String namedQuery, Object[] args, Parameter[] parameter) {
            TypedQuery<T> query = buildQuery(namedQuery, args, parameter);
            List<T> resultList = query.getResultList();
            return resultList.size() != 1 ? null : resultList.get(0);
        }

        @Override
        public List<T> executeListNamedQuery(String namedQuery, Object[] args, Parameter[] parameter) {
            TypedQuery<T> query = buildQuery(namedQuery, args, parameter);
            return query.getResultList();
        }

        @Override
        @SuppressWarnings("unchecked")
        public Page<T> executePageNamedQuery(String namedQuery, Object[] args, Parameter[] parameter) {
            TypedQuery<T> query = buildQuery(namedQuery, args, parameter);
            Page<T> page = Page.newInstance();
            for (Object arg : args) {
                if (arg.getClass() == Page.class) {
                    page = (Page<T>)arg;
                    break;
                }
            }
            List<T> entitiesList = query.setFirstResult(page.getPageSize() * (page.getPageNumber() - 1))
                .setMaxResults(page.getPageSize()).getResultList();
            page.setEntities(entitiesList);
            return page;
        }

        private TypedQuery<T> buildQuery(String namedQuery, Object[] args, Parameter[] parameter) {
            TypedQuery<T> query = this.entityManager.createNamedQuery(namedQuery, this.mainClass);
            if (args.length != parameter.length) {
                throw new TedException("参数异常");
            }
            Set<javax.persistence.Parameter<?>> params = query.getParameters();
            for (javax.persistence.Parameter<?> paramResolve : params) {

                for (int i = 0; i < args.length; i++) {
                    Parameter param = parameter[i];
                    Object arg = args[i];
                    Param paramAnnotation = param.getAnnotation(Param.class);
                    try {
                        Field field = null;
                        if (paramResolve.getName().equals(param.getName())
                            || (field = arg.getClass().getDeclaredField(paramResolve.getName())) != null) {
                            if (field != null) {
                                field.setAccessible(true);
                            }
                            query.setParameter(
                                paramAnnotation != null ? paramAnnotation.value() : paramResolve.getName(),
                                field == null ? args[i] : field.get(args[i]));
                        }
                    } catch (Exception e) {
                        continue;
                    }
                }

            }
            return query;
        }
    }

    public enum ExceptionCode {

        /**
         * 网络异常
         */
        NETWORK_ERROR,

        /*
         * 数据查询异常
         */
        DATA_QUERY_ERROR,

        /*
         * 数据修改异常
         */
        DATA_ALTER_ERROR,

        /**
         * 业务异常
         */
        BUSINESS_ERROR;
    }

    /**
     * 可显示的业务异常
     * 
     * @author Zhang Kangkang
     */
    public static class TedException extends RuntimeException {

        private static final long serialVersionUID = -7254665301232000989L;

        private String message;

        private ExceptionCode code = ExceptionCode.NETWORK_ERROR;

        public TedException() {
            super();
        }

        public TedException(String message) {
            super(message);
            this.message = message;
        }

        public TedException(String message, Throwable t) {
            super(message, t);
            this.message = message;
        }

        public TedException(String message, ExceptionCode code) {
            super(message);
            this.message = message;
            this.code = code;
        }

        public TedException(String message, ExceptionCode code, Throwable t) {
            super(message, t);
            this.message = message;
            this.code = code;
        }

        @Override
        public String toString() {
            return this.message + "[" + this.code + "]";
        }

    }

    /**
     * lambda字段查询，提取方法名内的字段属性
     *
     * @author Zhang Kangkang
     * @since 1.0
     */
    @FunctionalInterface
    public interface QueryFunction<T> extends Serializable {

        // final Logger LOGGER = LoggerFactory.getLogger(QueryFunction.class);

        final String GET_INSTANCE_NAME = "writeReplace";

        /**
         * 执行方法
         *
         * @param Target
         * @return
         */
        public Object apply(T Target);

        /**
         * 获取lambda表达式中方法名并提取字段属性
         *
         * @return 字段名
         */
        public default String getFieldName() {
            try {
                Method method = this.getClass().getDeclaredMethod(GET_INSTANCE_NAME);
                method.setAccessible(true);
                SerializedLambda lambdaInfo = (SerializedLambda)method.invoke(this);
                String getter = lambdaInfo.getImplMethodName();
                int methodLength = 5;
                String getMethod = "get";
                if (getter == null || getter.length() < methodLength || !getter.startsWith(getMethod)) {
                    throw new TedException("提取对象属性失败");
                }
                return getter.substring(3, 4).toLowerCase() + getter.substring(4);
            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                // if (LOGGER.isDebugEnabled()) {
                // LOGGER.debug("无法提取lambda内的writeReplace方法。", e);
                // }
                throw new TedException("提取对象属性失败");
            }

        }

    }

    /**
     * 获取属性值
     * 
     * @author Zhang Kangkang
     */
    @FunctionalInterface
    public interface GetFunction<T, E> extends QueryFunction<T> {

        // final Logger LOGGER = LoggerFactory.getLogger(GetFunction.class);

        /**
         * 获取lambda表达式中调用类
         *
         * @return 调用类
         */
        public default Class<?> getImplClasses() {
            try {
                Method method = this.getClass().getDeclaredMethod(GET_INSTANCE_NAME);
                method.setAccessible(true);
                SerializedLambda lambdaInfo = (SerializedLambda)method.invoke(this);;
                return Class.forName(lambdaInfo.getImplClass().replaceAll("/", "\\."));
            } catch (Exception e) {
                // if (LOGGER.isDebugEnabled()) {
                // LOGGER.debug("无法提取lambda内的实现类。", e);
                // }
                throw new TedException("提取对象实现类失败");
            }

        }

    }

    /**
     * 额外属性扩展方法
     * 
     * @author Zhang Kangkang
     */
    public static final class ExtraBuilder<T, E> implements Serializable {

        private static final long serialVersionUID = 1L;

        private Class<T> mainClass;

        private Class<E> extraClass;

        private String selectKey;

        private String property;

        private String linkedName;

        private String linkedValue;

        public static final String DEFAULT_KEY = "id";

        public Class<T> getMainClass() {
            return mainClass;
        }

        public void setMainClass(Class<T> mainClass) {
            this.mainClass = mainClass;
        }

        public Class<E> getExtraClass() {
            return extraClass;
        }

        public void setExtraClass(Class<E> extraClass) {
            this.extraClass = extraClass;
        }

        public String getSelectKey() {
            return selectKey;
        }

        public void setSelectKey(String selectKey) {
            this.selectKey = selectKey;
        }

        public String getProperty() {
            return property;
        }

        public void setProperty(String property) {
            this.property = property;
        }

        public String getLinkedName() {
            return linkedName;
        }

        public void setLinkedName(String linkedName) {
            this.linkedName = linkedName;
        }

        public String getLinkedValue() {
            return linkedValue;
        }

        public void setLinkedValue(String linkedValue) {
            this.linkedValue = linkedValue;
        }

        public static <T, E> ExtraBuilder<T, E> newInstance(Class<E> extraClass) {
            ExtraBuilder<T, E> builder = new ExtraBuilder<>();
            builder.setExtraClass(extraClass);
            return builder;
        }

    }

    /**
     * 自定义查询构造器
     *
     * @author Zhang Kangkang
     * @version 1.0.0
     */
    public interface QueryBuilder<T> extends Serializable {

        /**
         * 总记录数
         * 
         * @param em
         *            持久化管理器
         * @return Long
         */
        public Long count(EntityManager em);

        /**
         * 添加需要显示的字段
         *
         * @param fields
         *            显示字段
         * @return queryBuilder
         */
        public QueryBuilder<T> select(List<QueryFunction<T>> fields);

        /**
         * 添加需要显示的字段
         *
         * @param field
         *            显示字段
         * @return queryBuilder
         */
        public QueryBuilder<T> select(QueryFunction<T> field);

        /**
         * 添加不需要显示的字段
         *
         * @param field
         *            不需要显示的字段
         * @return queryBuilder
         */
        public QueryBuilder<T> selectExclude(QueryFunction<T> field);

        /**
         * 添加不需要显示的字段
         *
         * @param fields
         *            不需要显示的字段
         * @return queryBuilder
         */
        public QueryBuilder<T> selectExclude(List<QueryFunction<T>> fields);

        /**
         * 把实体内的属性按照属性名：属性值得方式用equals查询
         *
         * @param condition
         *            包含条件实体对象
         * @return queryBuilder
         */
        public QueryBuilder<T> condition(T condition);

        /**
         * 把实体内的属性按照属性名：属性值得方式用equals查询
         *
         * @param condition
         *            包含条件实体对象
         * @param type
         *            条件类型
         * @return queryBuilder
         */
        public QueryBuilder<T> condition(T condition, ConditionType type);

        /**
         * 平均数查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param function
         *            groupBy的字段
         * @param alias
         *            别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        public <E extends T> QueryBuilder<T> avg(QueryFunction<E> function, QueryFunction<E> alias);

        /**
         * 添加平均数查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param function
         *            需要查询的字段方法
         * @param alias
         *            查询的字段别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        public QueryBuilder<T> avg(QueryFunction<T> function, String alias);

        /**
         * 添加总条数查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param function
         *            需要查询的字段方法
         * @param alias
         *            查询的字段别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        public QueryBuilder<T> count(QueryFunction<T> function, QueryFunction<T> alias);

        /**
         * 添加总条数查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param function
         *            需要查询的字段方法
         * @param alias
         *            查询的字段别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        public QueryBuilder<T> count(QueryFunction<T> function, String alias);

        /**
         * 添加总条数（去重）查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param function
         *            需要查询的字段方法
         * @param alias
         *            查询的字段别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        public QueryBuilder<T> countDistinct(QueryFunction<T> function, QueryFunction<T> alias);

        /**
         * 添加总条数（去重）查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param function
         *            需要查询的字段方法
         * @param alias
         *            查询的字段别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        public QueryBuilder<T> countDistinct(QueryFunction<T> function, String alias);

        /**
         * 添加总和查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param function
         *            需要查询的字段方法
         * @param alias
         *            查询的字段别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        public QueryBuilder<T> sum(QueryFunction<T> function, QueryFunction<T> alias);

        /**
         * 添加总和查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param function
         *            需要查询的字段方法
         * @param alias
         *            查询的字段别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        public QueryBuilder<T> sum(QueryFunction<T> function, String alias);

        /**
         * 添加最大值查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param field
         *            字段名
         * @param alias
         *            别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        public QueryBuilder<T> max(QueryFunction<T> field, String alias);

        /**
         * 添加最大值查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param field
         *            字段名
         * @param alias
         *            别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        public QueryBuilder<T> max(QueryFunction<T> field, QueryFunction<T> alias);

        /**
         * 添加最小值查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param field
         *            字段名
         * @param alias
         *            别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        public QueryBuilder<T> min(QueryFunction<T> field, String alias);

        /**
         * 添加最小值查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param field
         *            字段名
         * @param alias
         *            别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        public QueryBuilder<T> min(QueryFunction<T> field, QueryFunction<T> alias);

        /**
         * 右模糊匹配
         *
         * @param function
         *            需要查询的字段
         * @param value
         *            需要模糊匹配的值
         * @return queryBuilder
         */
        public QueryBuilder<T> like(QueryFunction<T> field, String value);

        /**
         * 右模糊匹配
         *
         * @param executable
         *            是否执行
         * @param function
         *            需要查询的字段
         * @param value
         *            需要模糊匹配的值
         * @return queryBuilder
         */
        public QueryBuilder<T> like(Boolean executable, QueryFunction<T> field, String value);

        /**
         * 左右模糊匹配
         *
         * @param function
         *            需要查询的字段
         * @param value
         *            需要模糊匹配的值
         * @return queryBuilder
         */
        public QueryBuilder<T> allLike(QueryFunction<T> field, String value);

        /**
         * 左右模糊匹配
         *
         * @param executable
         *            是否执行
         * @param function
         *            需要查询的字段
         * @param value
         *            需要模糊匹配的值
         * @return queryBuilder
         */
        public QueryBuilder<T> allLike(Boolean executable, QueryFunction<T> field, String value);

        /**
         * 添加in条件
         *
         * @param field
         *            字段名
         * @param value
         *            集合值
         * @return
         */
        public QueryBuilder<T> in(QueryFunction<T> field, Collection<? extends Serializable> value);

        /**
         * 添加in条件
         *
         * @param field
         *            字段名
         * @param value
         *            集合值
         * @return
         */
        public QueryBuilder<T> in(QueryFunction<T> field, Serializable[] value);

        /**
         * 添加in条件
         *
         * @param field
         *            字段名
         * @param value
         *            集合值
         * @return
         */
        public QueryBuilder<T> in(String field, Collection<? extends Serializable> value);

        /**
         * 添加in条件
         *
         * @param field
         *            字段名
         * @param value
         *            集合值
         * @return
         */
        public QueryBuilder<T> in(String field, Serializable[] value);

        /**
         * 添加in条件
         *
         * @param executable
         *            是否执行
         * @param field
         *            字段名
         * @param value
         *            集合值
         * @return
         */
        public QueryBuilder<T> in(Boolean executable, QueryFunction<T> field, Collection<? extends Serializable> value);

        /**
         * 查询范围内的结果集
         *
         * @param field
         *            字段名
         * @param valueStart
         *            开始值
         * @param valueEnd
         *            结束值
         * @return queryBuilder
         */
        public <V extends Comparable<? super V>> QueryBuilder<T> between(QueryFunction<T> field, V valueStart,
            V valueEnd);

        /**
         * 查询范围内的结果集
         *
         * @param executable
         *            是否执行
         * @param field
         *            字段名
         * @param valueStart
         *            开始值
         * @param valueEnd
         *            结束值
         * @return queryBuilder
         */
        public <V extends Comparable<? super V>> QueryBuilder<T> between(Boolean executable, QueryFunction<T> field,
            V valueStart, V valueEnd);

        /**
         * 查询小于value范围内的结果集
         *
         * @param field
         *            字段名
         * @param value
         *            比较值
         * @return queryBuilder
         */
        public <V extends Comparable<? super V>> QueryBuilder<T> lessThan(QueryFunction<T> field, V value);

        /**
         * 查询小于value范围内的结果集
         *
         * @param executable
         *            是否执行
         * @param field
         *            字段名
         * @param value
         *            比较值
         * @return queryBuilder
         */
        public <V extends Comparable<? super V>> QueryBuilder<T> lessThan(Boolean executable, QueryFunction<T> field,
            V value);

        /**
         * 查询小于或等于value范围内的结果集
         *
         * @param field
         *            字段名
         * @param value
         *            比较值
         * @return queryBuilder
         */
        public <V extends Comparable<? super V>> QueryBuilder<T> lessThanOrEqualTo(QueryFunction<T> field, V value);

        /**
         * 查询小于或等于value范围内的结果集
         *
         * @param executable
         *            是否执行
         * @param field
         *            字段名
         * @param value
         *            比较值
         * @return queryBuilder
         */
        public <V extends Comparable<? super V>> QueryBuilder<T> lessThanOrEqualTo(Boolean executable,
            QueryFunction<T> field, V value);

        /**
         * 查询大于value范围内的结果集
         *
         * @param field
         *            字段名
         * @param value
         *            比较值
         * @return queryBuilder
         */
        public <V extends Comparable<? super V>> QueryBuilder<T> moreThan(QueryFunction<T> field, V value);

        /**
         * 查询大于value范围内的结果集
         *
         * @param executable
         *            是否执行
         * @param field
         *            字段名
         * @param value
         *            比较值
         * @return queryBuilder
         */
        public <V extends Comparable<? super V>> QueryBuilder<T> moreThan(Boolean executable, QueryFunction<T> field,
            V value);

        /**
         * 查询大于或等于value范围内的结果集
         *
         * @param field
         *            字段名
         * @param value
         *            比较值
         * @return queryBuilder
         */
        public <V extends Comparable<? super V>> QueryBuilder<T> moreThanOrEqualTo(QueryFunction<T> field, V value);

        /**
         * 查询大于或等于value范围内的结果集
         *
         * @param executable
         *            是否执行
         * @param field
         *            字段名
         * @param value
         *            比较值
         * @return queryBuilder
         */
        public <V extends Comparable<? super V>> QueryBuilder<T> moreThanOrEqualTo(Boolean executable,
            QueryFunction<T> field, V value);

        /**
         * 查询等于value的结果集
         *
         * @param field
         *            字段
         * @param value
         *            比较值
         * @return queryBuilder
         */
        public QueryBuilder<T> equal(QueryFunction<T> field, Object value);

        /**
         * 查询等于value的结果集
         *
         * @param executable
         *            是否执行
         * @param field
         *            字段
         * @param value
         *            比较值
         * @return queryBuilder
         */
        public QueryBuilder<T> equal(Boolean executable, QueryFunction<T> field, Object value);

        /**
         * 查询不等于value的结果集
         *
         * @param field
         *            字段
         * @param value
         *            比较值
         * @return queryBuilder
         */
        public QueryBuilder<T> notEqual(QueryFunction<T> field, Object value);

        /**
         * 查询不等于value的结果集
         *
         * @param executable
         *            是否执行
         * @param field
         *            字段
         * @param value
         *            比较值
         * @return queryBuilder
         */
        public QueryBuilder<T> notEqual(Boolean executable, QueryFunction<T> field, Object value);

        /**
         * 所有条件字段加入or判断
         *
         * @param field
         *            字段
         * @return queryBuilder
         */
        public QueryBuilder<T> or(List<QueryFunction<T>> field);

        /**
         * 添加groupBy的字段列表
         *
         * @param groupByList
         *            需要groupBy的字段列表
         * @return queryBuilder
         */
        public <E extends T> QueryBuilder<T> groupBy(List<QueryFunction<E>> groupByList);

        /**
         * 根据构造的排序链进行排序
         *
         * @param sortChain
         *            排序链
         * @return queryBuilder
         */
        public QueryBuilder<T> sort(SortChain sortChain);

        /**
         * 根据排序链进行排序
         *
         * @param sortChain
         *            排序链
         * @return queryBuilder
         */
        public QueryBuilder<T> orderBy(SortChain sortChain);

        /**
         * 将查询出的结果通过扩展查询，填入相关属性，属性将以bean的形式全部注入，所有被赋值对象必须包含相关set方法
         * 
         * @author Zhang KangKang
         * @param selectKey
         *            需要查询数据
         * @param linkedKey
         *            关联对象的属性与selectKey对应
         * @param beanProperty
         *            需要放入的对象属性
         * @return queryBuilder
         */
        public <E extends T, V> QueryBuilder<T> expand(GetFunction<? super E, ?> selectKey,
            GetFunction<? super V, ?> linkedKey, GetFunction<? super E, ?> beanProperty);

        /**
         * 将查询出的结果通过扩展查询，填入相关属性，属性将以单个属性的形式全部注入，所有被赋值对象必须包含相关set方法
         * 
         * @author Zhang KangKang
         * @param selectKey
         *            需要查询数据
         * @param linkedKey
         *            关联对象的属性与selectKey对应
         * @param linkedValue
         *            需要取出的值
         * @param beanProperty
         *            需要放入的对象属性
         * @return queryBuilder
         */
        public <E extends T, V> QueryBuilder<T> expand(GetFunction<? super E, ?> selectKey,
            GetFunction<? super V, ?> linkedKey, GetFunction<? super V, ?> linkedValue,
            GetFunction<? super E, ?> beanProperty);

        /**
         * 获取条件
         *
         * @return 条件列表
         */
        public List<ConditionHolder> getCondition();

        /**
         * 获取构造类
         *
         * @return 构造类
         */
        public Class<T> getMainClass();

        /**
         * 根据自定义条件查询列表
         * 
         * @author Zhang Kangkang
         * @param em
         *            持久化管理对象
         * @return List
         */
        public List<T> findList(EntityManager em);

        /**
         * 根据自定义条件查询列表，返回对象为传入的Class对象
         * 
         * @author Zhang Kangkang
         * @param instanceClass
         *            需要返回的对象类型
         * @param em
         *            持久化管理对象
         * @return List
         */
        public <E extends T> List<E> findList(Class<E> instanceClass, EntityManager em);

        /**
         * 根据自定义条件查询列表，返回对象为Map
         * 
         * @author Zhang Kangkang
         * @param em
         *            持久化管理对象
         * @return List<Map>
         */
        public List<Map<String, Object>> findListToMap(EntityManager em);

        /**
         * 根据自定义条件查询结果
         * 
         * @author Zhang Kangkang
         * @param em
         *            持久化管理对象
         * @return T
         */
        public T findOne(EntityManager em);

        /**
         * 根据自定义条件查询结果
         * 
         * @author Zhang Kangkang
         * @param cls
         *            返回的对象类型
         * @param em
         *            持久化管理对象
         * @return E
         */
        public <E extends T> E findOne(Class<E> cls, EntityManager em);

        /**
         * 根据自定义条件查询结果，返回对象为Map
         * 
         * @author Zhang Kangkang
         * @param em
         *            持久化管理对象
         * @return Map
         */
        public Map<String, Object> findOneToMap(EntityManager em);

        /**
         * 根据自定义条件查询分页结果
         * 
         * @author Zhang Kangkang
         * @param page
         *            分页条件
         * @param em
         *            持久化管理对象
         * @return Page<T>
         */
        public Page<T> findPage(Page<T> page, EntityManager em);

        /**
         * 根据自定义条件查询分页结果
         * 
         * @author Zhang Kangkang
         * @param page
         *            分页条件
         * @param cls
         *            返回对象类型
         * @param em
         *            持久化管理对象
         * @return Page<T>
         */
        public <E extends T> Page<E> findPage(Page<E> page, Class<E> cls, EntityManager em);

        /**
         * 根据自定义条件查询分页结果，返回Map对象
         * 
         * @author Zhang Kangkang
         * @param page
         *            分页条件
         * @param em
         *            持久化管理对象
         * @return Page<Map>
         */
        public Page<Map<String, Object>> findPageToMap(Page<Map<String, Object>> page, EntityManager em);

    }

    /**
     * 排序列
     *
     * @author Zhang Kangkang
     * @version 1.0.0
     */
    public static class SortChainBuilder implements Serializable {

        private static final long serialVersionUID = 1L;

        /**
         * 升序
         * 
         * @author Zhang Kangkang
         * @param function
         *            字段名
         * @return
         */
        public static <T> SortChain asc(QueryFunction<T> function) {
            return new SortChain(function.getFieldName(), Sortway.ASC);
        }

        /**
         * 升序
         * 
         * @author Zhang Kangkang
         * @param fieldName
         *            字段名
         * @return
         */
        public static <T> SortChain asc(String fieldName) {
            return new SortChain(fieldName, Sortway.ASC);
        }

        /**
         * 降序
         * 
         * @author Zhang Kangkang
         * @param function
         *            字段名
         * @return
         */
        public static <T> SortChain desc(QueryFunction<T> function) {
            return new SortChain(function.getFieldName(), Sortway.DESC);
        }

        /**
         * 降序
         * 
         * @author Zhang Kangkang
         * @param fieldName
         *            字段名
         * @return
         */
        public static <T> SortChain desc(String fieldName) {
            return new SortChain(fieldName, Sortway.DESC);
        }

    }

    public enum Sortway {
        ASC, DESC;
    }

    public static class SortChain implements Serializable {

        private static final long serialVersionUID = 1L;

        private List<SortChain> chain;

        private String name;

        private Sortway sortway;

        public SortChain() {}

        private SortChain(String name, Sortway sortway) {
            this.name = name;
            this.sortway = sortway;
            this.chain = new ArrayList<>(4);
            this.chain.add(this);
        }

        /**
         * 升序
         * 
         * @author Zhang Kangkang
         * @param function
         *            字段�?
         * @return
         */
        public <T> SortChain asc(QueryFunction<T> function) {
            this.chain.add(new SortChain(function.getFieldName(), Sortway.ASC));
            return this;
        }

        /**
         * 升序
         * 
         * @author Zhang Kangkang
         * @param fieldName
         *            字段�?
         * @return
         */
        public <T> SortChain asc(String fieldName) {
            this.chain.add(new SortChain(fieldName, Sortway.ASC));
            return this;
        }

        /**
         * 降序
         * 
         * @author Zhang Kangkang
         * @param function
         *            字段�?
         * @return
         */
        public <T> SortChain desc(QueryFunction<T> function) {
            this.chain.add(new SortChain(function.getFieldName(), Sortway.DESC));
            return this;
        }

        /**
         * 降序
         * 
         * @author Zhang Kangkang
         * @param fieldName
         *            字段�?
         * @return
         */
        public <T> SortChain desc(String fieldName) {
            this.chain.add(new SortChain(fieldName, Sortway.DESC));
            return this;
        }

        public List<SortChain> getChain() {
            return this.chain;
        }

        public String getName() {
            return this.name;
        }

        public Sortway getSortway() {
            return this.sortway;
        }

        public int getSize() {
            return this.chain.size();
        }

    }

    /**
     * 自定义查询构造器
     *
     * @author Zhang Kangkang
     * @version 1.0.0
     */
    public static class TupleQueryBuilder<T> implements QueryBuilder<T> {

        private static final long serialVersionUID = 1L;

        private List<ConditionHolder> conditions = new ArrayList<>();

        private List<ExtraBuilder<T, ?>> extraList = new ArrayList<>();

        /**
         * 查询like模糊匹配符号
         */
        public static final String FUZZY_MATCH = "%";

        /**
         * 持有的基类
         */
        private Class<T> mainClass;

        public TupleQueryBuilder() {}

        public TupleQueryBuilder(Class<T> mainClass) {
            this.mainClass = mainClass;
        }

        public TupleQueryBuilder<T> setMainClass(Class<T> mainClass) {
            this.mainClass = mainClass;
            return this;
        }

        private boolean doFilter(List<String> fieldList, String column, FilterMode filterMode) {
            return (filterMode == FilterMode.INCLUDE && !fieldList.contains(column))
                || (filterMode == FilterMode.EXCLUDE && fieldList.contains(column));
        }

        @Override
        public Long count(EntityManager em) {

            CriteriaBuilder builder = em.getCriteriaBuilder();

            CriteriaQuery<Tuple> conditionQuery = ConditionBuilder.build(this, em);
            Root<?> root = conditionQuery.getRoots().stream().findAny().get();
            conditionQuery.multiselect(builder.count(root));

            return em.createQuery(conditionQuery).getResultStream().findAny().get().get(0, Long.class);
        }

        /**
         * 添加需要显示的字段
         * 
         * @param fields
         *            显示字段
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> select(List<QueryFunction<T>> fields) {
            return doSelect(fields, FilterMode.INCLUDE);
        }

        /**
         * 添加需要显示的字段
         * 
         * @param field
         *            显示字段
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> select(QueryFunction<T> field) {
            return doSelect(Arrays.asList(field), FilterMode.INCLUDE);
        }

        /**
         * 添加不需要显示的字段
         * 
         * @param field
         *            不需要显示的字段
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> selectExclude(QueryFunction<T> field) {
            return doSelect(Arrays.asList(field), FilterMode.EXCLUDE);
        }

        /**
         * 添加不需要显示的字段
         * 
         * @param fields
         *            不需要显示的字段
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> selectExclude(List<QueryFunction<T>> fields) {
            return doSelect(fields, FilterMode.EXCLUDE);
        }

        private TupleQueryBuilder<T> doSelect(List<QueryFunction<T>> fields, FilterMode filterMode) {

            if (filterMode != FilterMode.INCLUDE && filterMode != FilterMode.EXCLUDE) {
                return this;
            }

            Set<String> columns = ReflectUtils.getColumns(this.mainClass);

            Set<String> filterColumn;
            if (filterMode == FilterMode.ALL) {
                filterColumn = columns;
            } else {
                List<String> fieldList = fields.stream().map(e -> e.getFieldName()).collect(Collectors.toList());
                filterColumn =
                    columns.stream().filter(e -> !doFilter(fieldList, e, filterMode)).collect(Collectors.toSet());
            }

            this.conditions.add(new ConditionHolder().setValue(filterColumn).setType(ConditionType.FIELD));

            return this;
        }

        /**
         * 平均数查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param function
         *            groupBy的字段
         * @param alias
         *            别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        @Override
        public <E extends T> TupleQueryBuilder<T> avg(QueryFunction<E> function, QueryFunction<E> alias) {
            this.conditions.add(new ConditionHolder().setName(function.getFieldName()).setAlias(alias.getFieldName())
                .setType(ConditionType.AVG));
            return this;
        }

        /**
         * 添加平均数查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param function
         *            需要查询的字段方法
         * @param alias
         *            查询的字段别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> avg(QueryFunction<T> function, String alias) {
            this.conditions
                .add(new ConditionHolder().setName(function.getFieldName()).setAlias(alias).setType(ConditionType.AVG));
            return this;
        }

        /**
         * 添加总条数查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param function
         *            需要查询的字段方法
         * @param alias
         *            查询的字段别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> count(QueryFunction<T> function, QueryFunction<T> alias) {

            this.conditions.add(new ConditionHolder().setName(function.getFieldName()).setAlias(alias.getFieldName())
                .setType(ConditionType.COUNT));

            return this;
        }

        /**
         * 添加总条数查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param function
         *            需要查询的字段方法
         * @param alias
         *            查询的字段别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> count(QueryFunction<T> function, String alias) {

            this.conditions.add(
                new ConditionHolder().setName(function.getFieldName()).setAlias(alias).setType(ConditionType.COUNT));

            return this;
        }

        /**
         * 添加总条数（去重）查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param function
         *            需要查询的字段方法
         * @param alias
         *            查询的字段别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> countDistinct(QueryFunction<T> function, QueryFunction<T> alias) {

            this.conditions.add(new ConditionHolder().setName(function.getFieldName()).setAlias(alias.getFieldName())
                .setType(ConditionType.COUNT_DISTINCT));
            return this;
        }

        /**
         * 添加总条数（去重）查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param function
         *            需要查询的字段方法
         * @param alias
         *            查询的字段别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> countDistinct(QueryFunction<T> function, String alias) {

            this.conditions.add(new ConditionHolder().setName(function.getFieldName()).setAlias(alias)
                .setType(ConditionType.COUNT_DISTINCT));

            return this;
        }

        /**
         * 添加总和查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param function
         *            需要查询的字段方法
         * @param alias
         *            查询的字段别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> sum(QueryFunction<T> function, QueryFunction<T> alias) {
            this.conditions.add(new ConditionHolder().setName(function.getFieldName()).setAlias(alias.getFieldName())
                .setType(ConditionType.SUM));

            return this;
        }

        /**
         * 添加总和查询字段，聚合函数构造结束前需要groupBy相应字段
         *
         * @param function
         *            需要查询的字段方法
         * @param alias
         *            查询的字段别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> sum(QueryFunction<T> function, String alias) {
            this.conditions
                .add(new ConditionHolder().setName(function.getFieldName()).setAlias(alias).setType(ConditionType.SUM));

            return this;
        }

        /**
         * 添加最大值查询字段，聚合函数构造结束前需要groupBy相应字段
         * 
         * @param field
         *            字段名
         * @param alias
         *            别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> max(QueryFunction<T> field, String alias) {

            this.conditions
                .add(new ConditionHolder().setName(field.getFieldName()).setAlias(alias).setType(ConditionType.MAX));

            return this;
        }

        /**
         * 添加最大值查询字段，聚合函数构造结束前需要groupBy相应字段
         * 
         * @param field
         *            字段名
         * @param alias
         *            别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> max(QueryFunction<T> field, QueryFunction<T> alias) {

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setAlias(alias.getFieldName())
                .setType(ConditionType.MAX));

            return this;
        }

        /**
         * 添加最小值查询字段，聚合函数构造结束前需要groupBy相应字段
         * 
         * @param field
         *            字段名
         * @param alias
         *            别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> min(QueryFunction<T> field, String alias) {

            this.conditions
                .add(new ConditionHolder().setName(field.getFieldName()).setAlias(alias).setType(ConditionType.MIN));

            return this;
        }

        /**
         * 添加最小值查询字段，聚合函数构造结束前需要groupBy相应字段
         * 
         * @param field
         *            字段名
         * @param alias
         *            别名, 需注意，如别名不存在字段中，可用Map接收返回值，否则抛出无方法异常。
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> min(QueryFunction<T> field, QueryFunction<T> alias) {

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setAlias(alias.getFieldName())
                .setType(ConditionType.MIN));

            return this;
        }

        /**
         * 把实体内的属性按照属性名：属性值得方式用equals查询
         * 
         * @param condition
         *            包含条件实体对象
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> condition(T condition) {
            if (condition != null) {
                Set<Method> methodSet = ReflectUtils.getAllGetterMethod(condition.getClass());
                methodSet.forEach(method -> {
                    try {
                        Object result = method.invoke(condition);
                        if (result != null) {

                            this.conditions.add(new ConditionHolder().setName(ReflectUtils.getGetterName(method))
                                .setAlias(ReflectUtils.getGetterName(method)).setValue(method.invoke(condition))
                                .setType(ConditionType.EQUAL));
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        throw new TedException("添加查询条件失败", ExceptionCode.DATA_QUERY_ERROR);
                    }
                });
            }
            return this;
        }

        /**
         * 把实体内的属性按照属性名：属性值得方式用equals查询
         *
         * @param condition
         *            包含条件实体对象
         * @param type
         *            条件类型
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> condition(T condition, ConditionType type) {
            if (condition != null) {
                Set<Method> methodSet = ReflectUtils.getAllGetterMethod(condition.getClass());
                methodSet.forEach(method -> {
                    try {
                        Object result = method.invoke(condition);
                        if (result != null) {

                            Object value = method.invoke(condition);
                            String name = ReflectUtils.getGetterName(method);
                            if (value instanceof String) {
                                if (type == ConditionType.ALL_LIKE) {
                                    allLike(name, (String)value);
                                    return;
                                }
                                if (type == ConditionType.LIKE) {
                                    like(name, (String)value);
                                    return;
                                }
                            }
                            this.conditions.add(new ConditionHolder().setName(name).setAlias(name).setValue(value)
                                .setType(ConditionType.EQUAL));

                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        throw new TedException("添加查询条件失败", ExceptionCode.DATA_QUERY_ERROR);
                    }
                });
            }
            return this;
        }

        /**
         * 右模糊匹配
         * 
         * @param function
         *            需要查询的字段
         * @param value
         *            需要模糊匹配的值
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> like(QueryFunction<T> field, String value) {

            return like(field.getFieldName(), value);
        }

        private TupleQueryBuilder<T> like(String name, String value) {

            this.conditions.add(new ConditionHolder().setName(name).setType(ConditionType.LIKE).setAlias(name)
                .setValue(value + FUZZY_MATCH));

            return this;
        }

        /**
         * 右模糊匹配
         * 
         * @param executable
         *            是否执行
         * @param function
         *            需要查询的字段
         * @param value
         *            需要模糊匹配的值
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> like(Boolean executable, QueryFunction<T> field, String value) {

            if (!executable) {
                return this;
            }

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setType(ConditionType.LIKE)
                .setAlias(field.getFieldName()).setValue(value + FUZZY_MATCH));

            return this;
        }

        /**
         * 左右模糊匹配
         * 
         * @param function
         *            需要查询的字段
         * @param value
         *            需要模糊匹配的值
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> allLike(QueryFunction<T> field, String value) {

            return allLike(field.getFieldName(), value);
        }

        private TupleQueryBuilder<T> allLike(String name, String value) {

            this.conditions.add(new ConditionHolder().setName(name).setType(ConditionType.LIKE).setAlias(name)
                .setValue(FUZZY_MATCH + value + FUZZY_MATCH));

            return this;
        }

        /**
         * 左右模糊匹配
         * 
         * @param executable
         *            是否执行
         * @param function
         *            需要查询的字段
         * @param value
         *            需要模糊匹配的值
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> allLike(Boolean executable, QueryFunction<T> field, String value) {
            if (!executable) {
                return this;
            }

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setType(ConditionType.LIKE)
                .setAlias(field.getFieldName()).setValue(FUZZY_MATCH + value + FUZZY_MATCH));

            return this;
        }

        /**
         * 添加in条件
         * 
         * @param field
         *            字段名
         * @param value
         *            集合值
         * @return
         */
        @Override
        public TupleQueryBuilder<T> in(QueryFunction<T> field, Collection<? extends Serializable> value) {

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setAlias(field.getFieldName())
                .setValue(value).setType(ConditionType.IN));

            return this;
        }

        /**
         * 添加in条件
         * 
         * @param field
         *            字段名
         * @param value
         *            集合值
         * @return
         */
        @Override
        public TupleQueryBuilder<T> in(QueryFunction<T> field, Serializable[] value) {

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setType(ConditionType.IN)
                .setAlias(field.getFieldName()).setValue(CollectionUtils.array2Set(value)));

            return this;
        }

        /**
         * 添加in条件
         * 
         * @param field
         *            字段名
         * @param value
         *            集合值
         * @return
         */
        @Override
        public TupleQueryBuilder<T> in(String field, Collection<? extends Serializable> value) {

            this.conditions
                .add(new ConditionHolder().setName(field).setAlias(field).setValue(value).setType(ConditionType.IN));

            return this;
        }

        /**
         * 添加in条件
         * 
         * @param field
         *            字段名
         * @param value
         *            集合值
         * @return
         */
        @Override
        public TupleQueryBuilder<T> in(String field, Serializable[] value) {

            this.conditions.add(new ConditionHolder().setName(field).setAlias(field)
                .setValue(CollectionUtils.array2Set(value)).setType(ConditionType.IN));

            return this;
        }

        /**
         * 添加in条件
         * 
         * @param executable
         *            是否执行
         * @param field
         *            字段名
         * @param value
         *            集合值
         * @return
         */
        @Override
        public TupleQueryBuilder<T> in(Boolean executable, QueryFunction<T> field,
            Collection<? extends Serializable> value) {

            if (!executable) {
                return this;
            }

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setAlias(field.getFieldName())
                .setValue(value).setType(ConditionType.IN));

            return this;
        }

        /**
         * 查询范围内的结果集
         * 
         * @param field
         *            字段名
         * @param valueStart
         *            开始值
         * @param valueEnd
         *            结束值
         * @return queryBuilder
         */
        @Override
        public <V extends Comparable<? super V>> TupleQueryBuilder<T> between(QueryFunction<T> field, V valueStart,
            V valueEnd) {

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setType(ConditionType.BETWEEN)
                .setAlias(field.getFieldName()).setValue(Arrays.asList(valueStart, valueEnd)));

            return this;
        }

        /**
         * 查询范围内的结果集
         * 
         * @param executable
         *            是否执行
         * @param field
         *            字段名
         * @param valueStart
         *            开始值
         * @param valueEnd
         *            结束值
         * @return queryBuilder
         */
        @Override
        public <V extends Comparable<? super V>> TupleQueryBuilder<T> between(Boolean executable,
            QueryFunction<T> field, V valueStart, V valueEnd) {

            if (!executable) {
                return this;
            }

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setType(ConditionType.BETWEEN)
                .setAlias(field.getFieldName()).setValue(new Object[] {valueStart, valueEnd}));

            return this;
        }

        /**
         * 查询小于value范围内的结果集
         * 
         * @param field
         *            字段名
         * @param value
         *            比较值
         * @return queryBuilder
         */
        @Override
        public <V extends Comparable<? super V>> TupleQueryBuilder<T> lessThan(QueryFunction<T> field, V value) {

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setAlias(field.getFieldName())
                .setValue(value).setType(ConditionType.LESS_THAN));

            return this;
        }

        /**
         * 查询小于value范围内的结果集
         * 
         * @param executable
         *            是否执行
         * @param field
         *            字段名
         * @param value
         *            比较值
         * @return queryBuilder
         */
        @Override
        public <V extends Comparable<? super V>> TupleQueryBuilder<T> lessThan(Boolean executable,
            QueryFunction<T> field, V value) {

            if (!executable) {
                return this;
            }

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setAlias(field.getFieldName())
                .setValue(value).setType(ConditionType.LESS_THAN));

            return this;
        }

        /**
         * 查询小于或等于value范围内的结果集
         * 
         * @param field
         *            字段名
         * @param value
         *            比较值
         * @return queryBuilder
         */
        @Override
        public <V extends Comparable<? super V>> TupleQueryBuilder<T> lessThanOrEqualTo(QueryFunction<T> field,
            V value) {

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setAlias(field.getFieldName())
                .setValue(value).setType(ConditionType.LESS_THAN_OR_EQUAL_TO));

            return this;
        }

        /**
         * 查询小于或等于value范围内的结果集
         * 
         * @param executable
         *            是否执行
         * @param field
         *            字段名
         * @param value
         *            比较值
         * @return queryBuilder
         */
        @Override
        public <V extends Comparable<? super V>> TupleQueryBuilder<T> lessThanOrEqualTo(Boolean executable,
            QueryFunction<T> field, V value) {

            if (!executable) {
                return this;
            }

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setAlias(field.getFieldName())
                .setValue(value).setType(ConditionType.LESS_THAN_OR_EQUAL_TO));

            return this;
        }

        /**
         * 查询大于value范围内的结果集
         * 
         * @param field
         *            字段名
         * @param value
         *            比较值
         * @return queryBuilder
         */
        @Override
        public <V extends Comparable<? super V>> TupleQueryBuilder<T> moreThan(QueryFunction<T> field, V value) {

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setAlias(field.getFieldName())
                .setValue(value).setType(ConditionType.MORE_THAN));

            return this;
        }

        /**
         * 查询大于value范围内的结果集
         * 
         * @param executable
         *            是否执行
         * @param field
         *            字段名
         * @param value
         *            比较值
         * @return queryBuilder
         */
        @Override
        public <V extends Comparable<? super V>> TupleQueryBuilder<T> moreThan(Boolean executable,
            QueryFunction<T> field, V value) {

            if (!executable) {
                return this;
            }

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setAlias(field.getFieldName())
                .setValue(value).setType(ConditionType.MORE_THAN));

            return this;
        }

        /**
         * 查询大于或等于value范围内的结果集
         * 
         * @param field
         *            字段名
         * @param value
         *            比较值
         * @return queryBuilder
         */
        @Override
        public <V extends Comparable<? super V>> TupleQueryBuilder<T> moreThanOrEqualTo(QueryFunction<T> field,
            V value) {

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setAlias(field.getFieldName())
                .setValue(value).setType(ConditionType.MORE_THAN_OR_EQUAL_TO));

            return this;
        }

        /**
         * 查询大于或等于value范围内的结果集
         * 
         * @param executable
         *            是否执行
         * @param field
         *            字段名
         * @param value
         *            比较值
         * @return queryBuilder
         */
        @Override
        public <V extends Comparable<? super V>> TupleQueryBuilder<T> moreThanOrEqualTo(Boolean executable,
            QueryFunction<T> field, V value) {

            if (!executable) {
                return this;
            }

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setAlias(field.getFieldName())
                .setValue(value).setType(ConditionType.MORE_THAN_OR_EQUAL_TO));

            return this;
        }

        /**
         * 查询等于value的结果集
         * 
         * @param field
         *            字段
         * @param value
         *            比较值
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> equal(QueryFunction<T> field, Object value) {

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setAlias(field.getFieldName())
                .setValue(value).setType(ConditionType.EQUAL));

            return this;
        }

        /**
         * 查询等于value的结果集
         * 
         * @param executable
         *            是否执行
         * @param field
         *            字段
         * @param value
         *            比较值
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> equal(Boolean executable, QueryFunction<T> field, Object value) {

            if (!executable) {
                return this;
            }

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setAlias(field.getFieldName())
                .setValue(value).setType(ConditionType.EQUAL));

            return this;
        }

        /**
         * 查询不等于value的结果集
         * 
         * @param field
         *            字段
         * @param value
         *            比较值
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> notEqual(QueryFunction<T> field, Object value) {

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setAlias(field.getFieldName())
                .setValue(value).setType(ConditionType.NOT_EQUAL));

            return this;
        }

        /**
         * 查询不等于value的结果集
         * 
         * @param executable
         *            是否执行
         * @param field
         *            字段
         * @param value
         *            比较值
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> notEqual(Boolean executable, QueryFunction<T> field, Object value) {

            this.conditions.add(new ConditionHolder().setName(field.getFieldName()).setAlias(field.getFieldName())
                .setValue(value).setType(ConditionType.NOT_EQUAL));

            return this;
        }

        @Override
        public TupleQueryBuilder<T> or(List<QueryFunction<T>> field) {

            this.conditions.add(new ConditionHolder().setValue(field).setType(ConditionType.OR));

            return this;
        }

        /**
         * 添加groupBy的字段列表
         *
         * @param groupByList
         *            需要groupBy的字段列表
         * @return queryBuilder
         */
        @Override
        public <E extends T> TupleQueryBuilder<T> groupBy(List<QueryFunction<E>> groupByList) {

            this.conditions.add(new ConditionHolder().setValue(groupByList).setType(ConditionType.GROUP_BY));

            return this;
        }

        /**
         * 根据构造的排序链进行排序
         * 
         * @param sortChain
         *            排序链
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> sort(SortChain sortChain) {

            this.conditions.add(new ConditionHolder().setValue(sortChain).setType(ConditionType.ORDER_BY));

            return this;
        }

        /**
         * 根据排序链进行排序
         * 
         * @param sortChain
         *            排序链
         * @return queryBuilder
         */
        @Override
        public TupleQueryBuilder<T> orderBy(SortChain sortChain) {
            sort(sortChain);
            return this;
        }

        @SuppressWarnings("unchecked")
        public <E extends T, V> QueryBuilder<T> extra(GetFunction<? super E, ?> selectKey,
            GetFunction<? super V, ?> linkedKey, GetFunction<? super V, ?> linkedValue,
            GetFunction<? super E, ?> property) {

            ExtraBuilder<E, V> extraBuilder = (ExtraBuilder<E, V>)ExtraBuilder.newInstance(linkedKey.getImplClasses());
            extraBuilder.setSelectKey(selectKey.getFieldName());
            extraBuilder.setProperty(property.getFieldName());
            extraBuilder.setLinkedName(linkedKey.getFieldName());
            extraBuilder.setLinkedValue(linkedValue != null ? linkedValue.getFieldName() : null);
            extraList.add((ExtraBuilder<T, ?>)extraBuilder);

            return this;
        }

        @Override
        public <E extends T, V> QueryBuilder<T> expand(GetFunction<? super E, ?> selectKey,
            GetFunction<? super V, ?> linkedKey, GetFunction<? super E, ?> beanProperty) {

            return extra(selectKey, linkedKey, null, beanProperty);
        }

        @Override
        public <E extends T, V> QueryBuilder<T> expand(GetFunction<? super E, ?> selectKey,
            GetFunction<? super V, ?> linkedKey, GetFunction<? super V, ?> linkedValue,
            GetFunction<? super E, ?> beanProperty) {

            return extra(selectKey, linkedKey, linkedValue, beanProperty);
        }

        private <E> List<E> buildListByClass(Class<E> instanceClass, List<Tuple> list) {

            List<E> resultList = new ArrayList<>(list.size());
            try {
                for (Tuple tuple : list) {
                    E instance = instanceClass.newInstance();
                    for (TupleElement<?> element : tuple.getElements()) {
                        Method setter = instanceClass.getMethod(ReflectUtils.getSetterName(element.getAlias()),
                            element.getJavaType());
                        setter.invoke(instance, tuple.get(element.getAlias()));
                    }
                    resultList.add(instance);
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new TedException("查询列表失败", ExceptionCode.DATA_QUERY_ERROR);
            }
            return resultList;
        }

        private List<Map<String, Object>> buildListByMap(List<Tuple> list) {

            List<Map<String, Object>> resultList = new ArrayList<>(list.size());
            for (Tuple tuple : list) {
                Map<String, Object> instance = new HashMap<>(list.size());
                for (TupleElement<?> element : tuple.getElements()) {
                    instance.put(element.getAlias(), tuple.get(element.getAlias()));
                }
                resultList.add(instance);
            }

            return resultList;
        }

        private <E> E buildOneByClass(Class<E> instanceClass, Tuple tupleOptional) {

            try {
                E instance = instanceClass.newInstance();
                if (tupleOptional == null) {
                    return null;
                }
                for (TupleElement<?> element : tupleOptional.getElements()) {
                    Method setter =
                        instanceClass.getMethod(ReflectUtils.getSetterName(element.getAlias()), element.getJavaType());
                    setter.invoke(instance, tupleOptional.get(element.getAlias()));
                }
                return instance;
            } catch (Exception e) {
                e.printStackTrace();
                throw new TedException("添加对象失败", ExceptionCode.DATA_QUERY_ERROR);
            }
        }

        private Map<String, Object> buildOneByMap(Tuple tupleOptional) {

            try {
                Map<String, Object> instance = new HashMap<>();
                if (tupleOptional == null) {
                    return null;
                }
                for (TupleElement<?> element : tupleOptional.getElements()) {
                    instance.put(element.getAlias(), tupleOptional.get(element.getAlias()));
                }
                return instance;
            } catch (Exception e) {
                e.printStackTrace();
                throw new TedException("查询对象失败", ExceptionCode.BUSINESS_ERROR);
            }
        }

        /**
         * 根据自定义条件查询列表
         * 
         * @author Zhang Kangkang
         * @param em
         *            持久化管理对象
         * @return List
         */
        @Override
        public List<T> findList(EntityManager em) {
            return buildListByClass(this.mainClass, ConditionBuilder.getQuery(this, em).getResultList());
        }

        /**
         * 根据自定义条件查询列表，返回对象为传入的Class对象
         * 
         * @author Zhang Kangkang
         * @param instanceClass
         *            需要返回的对象类型
         * @param em
         *            持久化管理对象
         * @return List
         */
        @Override
        public <E extends T> List<E> findList(Class<E> instanceClass, EntityManager em) {
            List<E> result = buildListByClass(instanceClass, ConditionBuilder.getQuery(this, em).getResultList());
            fillExtra(result, instanceClass, em);
            return result;
        }

        /**
         * 根据自定义条件查询列表，返回对象为Map
         * 
         * @author Zhang Kangkang
         * @param em
         *            持久化管理对象
         * @return List<Map>
         */
        @Override
        public List<Map<String, Object>> findListToMap(EntityManager em) {
            List<Map<String, Object>> result = buildListByMap(ConditionBuilder.getQuery(this, em).getResultList());
            fillExtraToMap(result, em);
            return result;
        }

        /**
         * 根据自定义条件查询结果
         * 
         * @author Zhang Kangkang
         * @param em
         *            持久化管理对象
         * @return T
         */
        @Override
        public T findOne(EntityManager em) {
            Optional<Tuple> result = ConditionBuilder.getQuery(this, em).getResultStream().findFirst();

            return buildOneByClass(this.mainClass, result.isPresent() ? result.get() : null);
        }

        /**
         * 根据自定义条件查询结果
         * 
         * @author Zhang Kangkang
         * @param cls
         *            返回的对象类型
         * @param em
         *            持久化管理对象
         * @return E
         */
        @Override
        public <E extends T> E findOne(Class<E> cls, EntityManager em) {
            Optional<Tuple> result = ConditionBuilder.getQuery(this, em).getResultStream().findFirst();
            E data = buildOneByClass(cls, result.isPresent() ? result.get() : null);
            fillExtra(Arrays.asList(data), cls, em);
            return data;
        }

        /**
         * 根据自定义条件查询结果，返回对象为Map
         * 
         * @author Zhang Kangkang
         * @param em
         *            持久化管理对象
         * @return Map
         */
        @Override
        public Map<String, Object> findOneToMap(EntityManager em) {
            Optional<Tuple> result = ConditionBuilder.getQuery(this, em).getResultStream().findFirst();

            Map<String, Object> data = buildOneByMap(result.isPresent() ? result.get() : null);
            fillExtraToMap(Arrays.asList(data), em);

            return data;
        }

        /**
         * 根据自定义条件查询分页结果
         * 
         * @author Zhang Kangkang
         * @param page
         *            分页条件
         * @param em
         *            持久化管理对象
         * @return Page<T>
         */
        @Override
        public Page<T> findPage(Page<T> page, EntityManager em) {
            addSort(this, page);
            List<Tuple> list =
                ConditionBuilder.getQuery(this, em).setFirstResult(page.getPageSize() * (page.getPageNumber() - 1))
                    .setMaxResults(page.getPageSize()).getResultList();
            List<T> result = buildListByClass(this.mainClass, list);
            page.setCount(count(em));
            page.setEntities(result);
            return page;
        }

        /**
         * 为分页添加排序
         * 
         * @author Zhang Kangkang
         * @param queryBuilder
         *            条件构造器
         * @param page
         *            分页参数
         */
        private void addSort(TupleQueryBuilder<T> queryBuilder, Page<?> page) {

            if ((page.getDescs() != null && page.getDescs().size() > 0)
                || (page.getAscs() != null && page.getAscs().size() > 0)) {

                SortChain sortChain = null;
                if (page.getDescs().size() > 0) {
                    for (String desc : page.getDescs()) {
                        if (sortChain == null) {
                            sortChain = SortChainBuilder.desc(desc);
                        } else {
                            sortChain.desc(desc);
                        }
                    }
                }

                if (page.getAscs().size() > 0) {
                    for (String asc : page.getAscs()) {
                        if (sortChain == null) {
                            sortChain = SortChainBuilder.asc(asc);
                        } else {
                            sortChain.asc(asc);
                        }
                    }
                }
                queryBuilder.sort(sortChain);
            }
        }

        /**
         * 根据自定义条件查询分页结果
         * 
         * @author Zhang Kangkang
         * @param page
         *            分页条件
         * @param cls
         *            返回对象类型
         * @param em
         *            持久化管理对象
         * @return Page<T>
         */
        @Override
        public <E extends T> Page<E> findPage(Page<E> page, Class<E> cls, EntityManager em) {
            addSort(this, page);
            List<Tuple> list =
                ConditionBuilder.getQuery(this, em).setFirstResult(page.getPageSize() * (page.getPageNumber() - 1))
                    .setMaxResults(page.getPageSize()).getResultList();

            List<E> result = buildListByClass(cls, list);

            fillExtra(result, cls, em);

            page.setCount(count(em));
            page.setEntities(result);
            return page;
        }

        private <E extends T> void fillExtraToMap(List<Map<String, Object>> result, EntityManager em) {

            if (result.size() == 0) {
                return;
            }

            this.extraList.stream().forEach(extra -> {

                Set<Object> extraIdSet =
                    result.stream().map(e -> e.get(extra.getSelectKey())).collect(Collectors.toSet());

                CriteriaBuilder builder = em.getCriteriaBuilder();
                CriteriaQuery<Tuple> query = builder.createTupleQuery();
                Root<?> root = query.from(extra.getExtraClass());

                String linkedName = extra.getLinkedName();
                String linkedValue = extra.getLinkedValue();

                if (linkedValue == null) {
                    List<Selection<?>> selects = new ArrayList<>(10);
                    Set<String> columns = ReflectUtils.getColumns(extra.getExtraClass());
                    columns.forEach(column -> {
                        selects.add(root.get(column).alias(column));
                    });
                    query.multiselect(selects);
                } else {
                    query.multiselect(root.get(linkedName).alias(linkedName), root.get(linkedValue).alias(linkedValue));
                }

                query.where(new Predicate[] {root.get(linkedName).in(extraIdSet)});

                Stream<Tuple> extraStream = em.createQuery(query).getResultStream();
                Map<Object, Object> extraMap = new HashMap<>();

                extraStream.forEach(e -> {
                    if (linkedValue == null) {
                        Map<String, Object> valueMap = new HashMap<>();
                        e.getElements().forEach(key -> {
                            valueMap.put(key.getAlias(), e.get(key.getAlias()));
                        });
                        extraMap.put(e.get(linkedName), valueMap);
                        return;
                    }
                    extraMap.put(e.get(linkedName), e.get(linkedValue));
                });

                result.stream().forEach(e -> {
                    e.put(extra.getProperty(), extraMap.get(e.get(extra.getSelectKey())));
                });
            });

        }

        private <E extends T> void fillExtra(List<E> result, Class<E> cls, EntityManager em) {

            if (result.size() == 0) {
                return;
            }

            this.extraList.stream().forEach(extra -> {

                Field valueField;
                try {
                    valueField = this.mainClass.getDeclaredField(extra.getSelectKey());
                    valueField.setAccessible(true);
                } catch (Exception ex) {
                    ex.printStackTrace();
                    throw new TedException("填充额外值错误", ExceptionCode.BUSINESS_ERROR, ex);
                }
                Set<?> extraIdSet = result.stream().map(e -> {
                    try {
                        return valueField.get(e);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                        throw new TedException("填充额外值错误", ExceptionCode.BUSINESS_ERROR, ex);
                    }
                }).collect(Collectors.toSet());

                CriteriaBuilder builder = em.getCriteriaBuilder();
                CriteriaQuery<Tuple> query = builder.createTupleQuery();
                Root<?> root = query.from(extra.getExtraClass());

                String linkedName = extra.getLinkedName();
                String linkedValue = extra.getLinkedValue();

                if (linkedValue == null) {
                    List<Selection<?>> selects = new ArrayList<>(10);
                    Set<String> columns = ReflectUtils.getColumns(extra.getExtraClass());
                    columns.forEach(column -> {
                        selects.add(root.get(column).alias(column));
                    });
                    query.multiselect(selects);
                } else {
                    query.multiselect(root.get(linkedName).alias(linkedName), root.get(linkedValue).alias(linkedValue));
                }
                query.where(new Predicate[] {root.get(linkedName).in(extraIdSet)});

                Stream<Tuple> extraStream = em.createQuery(query).getResultStream();
                Map<Object, Object> extraMap = new HashMap<>();

                extraStream.forEach(e -> {
                    extraMap.put(e.get(linkedName),
                        linkedValue == null ? buildOneByClass(extra.getExtraClass(), e) : e.get(linkedValue));
                });

                result.stream().forEach(e -> {

                    try {
                        Object mapped = extraMap.get(valueField.get(e));
                        Field field = cls.getDeclaredField(extra.getProperty());
                        field.setAccessible(true);
                        field.set(e, mapped);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                        throw new TedException("填充额外值错误", ExceptionCode.BUSINESS_ERROR, ex);
                    }
                });

            });

        }

        /**
         * 根据自定义条件查询分页结果，返回Map对象
         * 
         * @author Zhang Kangkang
         * @param page
         *            分页条件
         * @param em
         *            持久化管理对象
         * @return Page<Map>
         */
        @Override
        public Page<Map<String, Object>> findPageToMap(Page<Map<String, Object>> page, EntityManager em) {

            addSort(this, page);
            List<Tuple> list =
                ConditionBuilder.getQuery(this, em).setFirstResult(page.getPageSize() * (page.getPageNumber() - 1))
                    .setMaxResults(page.getPageSize()).getResultList();
            List<Map<String, Object>> result = buildListByMap(list);

            fillExtraToMap(result, em);

            page.setCount(count(em));
            page.setEntities(result);
            return page;
        }

        /**
         * 获取条件对象
         * 
         * @author Zhang Kangkang
         */
        @Override
        public List<ConditionHolder> getCondition() {
            return this.conditions;
        }

        /**
         * 获取Class对象
         * 
         * @author Zhang Kangkang
         */
        @Override
        public Class<T> getMainClass() {
            return this.mainClass;
        }

    }

    /**
     * 条件构造
     * 
     * @author ZhangKang
     */
    public static class ConditionBuilder {

        /**
         * 构建最终条件
         * 
         * @author Zhang Kangkang
         * @param queryBuilder
         *            自定义的条件构造类
         * @param em
         *            持久化管理器
         * @return TypedQuery
         */
        public static <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> CriteriaQuery<Tuple>
            build(QueryBuilder<T> queryBuilder, EntityManager em) {

            CriteriaBuilder builder = em.getCriteriaBuilder();
            CriteriaQuery<Tuple> query = builder.createTupleQuery();
            Root<T> root = query.from(queryBuilder.getMainClass());

            List<ConditionHolder> conditions = queryBuilder.getCondition();

            List<Selection<?>> selects = new ArrayList<>(10);
            List<Predicate> wheres = new ArrayList<>(4);
            List<Expression<?>> groupBy = new ArrayList<>(4);
            List<Order> orderBy = new ArrayList<>(4);
            List<QueryFunction<T>> orList = new ArrayList<>(4);

            for (ConditionHolder holder : conditions) {

                holder.getType().build(holder, builder, root, selects, wheres, groupBy, orderBy, orList);

            }

            if (selects.size() > 0) {
                query.multiselect(selects);
            } else {
                Set<String> columns = ReflectUtils.getColumns(queryBuilder.getMainClass());
                columns.forEach(column -> {
                    selects.add(root.get(column).alias(column));
                });
                query.multiselect(selects);
            }

            if (wheres.size() > 0) {

                if (orList.size() > 0) {
                    Set<String> aliasSet = orList.stream().map(e -> e.getFieldName()).collect(Collectors.toSet());
                    List<Predicate> oldPredicate = new ArrayList<>(wheres.size() - orList.size());
                    List<Predicate> orPredicate = new ArrayList<>(orList.size());

                    for (Predicate where : wheres) {
                        if (aliasSet.contains(where.getAlias())) {
                            orPredicate.add(where);
                            continue;
                        }
                        oldPredicate.add(where);
                    }

                    wheres = new ArrayList<>();
                    wheres.add(builder.and(oldPredicate.toArray(new Predicate[oldPredicate.size()])));
                    wheres.add(builder.or(orPredicate.toArray(new Predicate[orPredicate.size()])));
                }
                query.where(wheres.toArray(new Predicate[wheres.size()]));

            }

            if (groupBy.size() > 0) {
                query.groupBy(groupBy.toArray(new Expression[groupBy.size()]));
            }

            if (orderBy.size() > 0) {
                query.orderBy(orderBy);
            }

            return query;

        }

        public static <T> TypedQuery<Tuple> getQuery(QueryBuilder<T> queryBuilder, EntityManager em) {
            return em.createQuery(build(queryBuilder, em));
        }

    }

    /**
     * 条件代理对象
     * 
     * @author Zhang Kangkang
     */
    public static class ConditionHolder {

        String alias;

        Object value;

        String name;

        ConditionType type;

        public String getAlias() {
            return alias;
        }

        public ConditionHolder setAlias(String alias) {
            this.alias = alias;
            return this;
        }

        public Object getValue() {
            return value;

        }

        public ConditionHolder setValue(Object value) {
            this.value = value;
            return this;
        }

        public String getName() {
            return this.name;
        }

        public ConditionHolder setName(String name) {
            this.name = name;
            return this;
        }

        public ConditionType getType() {
            return type;
        }

        public ConditionHolder setType(ConditionType type) {
            this.type = type;
            return this;
        }

    }

    /**
     * 条件类型
     * 
     * @author Zhang Kangkang
     */
    public enum ConditionType {

        /**
         * 等于
         */
        EQUAL {

            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {

                Predicate equal = builder.equal(root.get(holder.getName()), holder.getValue());
                equal.alias(holder.getAlias());

                wheres.add(equal);
            }
        },

        /**
         * 不等于
         */
        NOT_EQUAL {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {

                Predicate notEqual = builder.notEqual(root.get(holder.getName()), holder.getValue());
                notEqual.alias(holder.getAlias());

                wheres.add(notEqual);

            }
        },

        /**
         * 或
         */
        OR {
            @SuppressWarnings("unchecked")
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {

                orList = (List<QueryFunction<T>>)holder.getValue();

            }
        },

        /**
         * 和
         */
        AND {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {

            }
        },

        /**
         * 字段
         */
        FIELD {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {

                @SuppressWarnings("unchecked")
                Set<String> fields = (Set<String>)holder.getValue();
                fields.forEach(field -> {
                    selects.add(root.get(field).alias(field));
                });

            }
        },

        /**
         * 平均数
         */
        AVG {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {
                Expression<?> avg = builder.avg(root.get(holder.getName()));
                avg.alias(holder.getAlias());

                selects.add(avg);
            }
        },

        /**
         * 总条数
         */
        COUNT {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {
                Expression<?> count = builder.count(root.get(holder.getName()));
                count.alias(holder.getAlias());

                selects.add(count);
            }
        },

        /**
         * 总条数（去除重复字段）
         */
        COUNT_DISTINCT {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {
                Expression<?> countDistinct = builder.countDistinct(root.get(holder.getName()));
                countDistinct.alias(holder.getAlias());

                selects.add(countDistinct);
            }
        },

        /**
         * 最大值
         */
        MAX {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {

                Expression<?> max = builder.max(root.get(holder.getName()));
                max.alias(holder.getAlias());

                selects.add(max);

            }
        },

        /**
         * 最小值
         */
        MIN {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {

                Expression<?> min = builder.min(root.get(holder.getName()));
                min.alias(holder.getAlias());

                selects.add(min);

            }
        },

        /**
         * 模糊
         */
        LIKE {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {

                Predicate like = builder.like(root.get(holder.getName()), String.valueOf(holder.getValue()));
                like.alias(holder.getAlias());

                wheres.add(like);

            }
        },

        /**
         * 左右模糊
         */
        ALL_LIKE {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {
                Predicate allLike = builder.like(root.get(holder.getName()), String.valueOf(holder.getValue()));
                allLike.alias(holder.getAlias());

                wheres.add(allLike);
            }
        },

        /**
         * 集合
         */
        IN {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {

                Predicate in = root.get(holder.getName()).in((Collection<?>)holder.getValue());
                in.alias(holder.getAlias());

                wheres.add(in);

            }
        },

        /**
         * 范围
         */
        BETWEEN {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {
                @SuppressWarnings("unchecked")
                List<V> value = (List<V>)holder.getValue();
                Predicate between = builder.between(root.get(holder.getName()), value.get(0), value.get(1));
                between.alias(holder.getAlias());

                wheres.add(between);
            }
        },

        /**
         * 小于
         */
        LESS_THAN {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {

                @SuppressWarnings("unchecked")
                Predicate lessThan = builder.lessThan(root.get(holder.getName()), (V)holder.getValue());
                lessThan.alias(holder.getAlias());

                wheres.add(lessThan);

            }
        },

        /**
         * 小于或等于
         */
        LESS_THAN_OR_EQUAL_TO {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {

                @SuppressWarnings("unchecked")
                Predicate lessThanOrEqualTo =
                    builder.lessThanOrEqualTo(root.get(holder.getName()), (V)holder.getValue());
                lessThanOrEqualTo.alias(holder.getAlias());

                wheres.add(lessThanOrEqualTo);

            }
        },

        /**
         * 大于
         */
        MORE_THAN {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {

                @SuppressWarnings("unchecked")
                Predicate moreThan = builder.greaterThan(root.get(holder.getName()), (V)holder.getValue());
                moreThan.alias(holder.getAlias());

                wheres.add(moreThan);

            }
        },

        /**
         * 大于或等于
         */
        MORE_THAN_OR_EQUAL_TO {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {

                @SuppressWarnings("unchecked")
                Predicate moreThanOrEqualTo =
                    builder.greaterThanOrEqualTo(root.get(holder.getName()), (V)holder.getValue());
                moreThanOrEqualTo.alias(holder.getAlias());

                wheres.add(moreThanOrEqualTo);

            }
        },

        /**
         * 分组
         */
        GROUP_BY {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {

                @SuppressWarnings("unchecked")
                List<QueryFunction<T>> queryFunctionList = (List<QueryFunction<T>>)holder.getValue();
                queryFunctionList.forEach(e -> {
                    Expression<T> group = root.get(e.getFieldName());
                    group.alias(e.getFieldName());
                    groupBy.add(group);
                });

            }
        },

        /**
         * 排序
         */
        ORDER_BY {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {

                SortChain sortChain = (SortChain)holder.getValue();

                for (int index = 0; index < sortChain.getSize(); index++) {
                    SortChain sort = sortChain.getChain().get(index);
                    if (sort.getSortway() == Sortway.ASC) {
                        orderBy.add(builder.asc(root.get(sort.getName())));
                    } else {
                        orderBy.add(builder.desc(root.get(sort.getName())));
                    }
                }

            }
        },
        /**
         * 总和
         */
        SUM {
            @Override
            <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(ConditionHolder holder,
                CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects, List<Predicate> wheres,
                List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList) {

                Expression<?> sum = builder.sum(root.get(holder.getName()));
                sum.alias(holder.getAlias());

                selects.add(sum);

            }
        };

        abstract <T, Y extends Comparable<? super Y>, V extends Comparable<? super V>> void build(
            ConditionHolder holder, CriteriaBuilder builder, Root<T> root, List<Selection<?>> selects,
            List<Predicate> wheres, List<Expression<?>> groupBy, List<Order> orderBy, List<QueryFunction<T>> orList);

    }

    /**
     * 基本服务接口
     *
     * @author Zhang Kangkang
     * @version 1.0.0
     */
    public interface ServiceRepository<T, ID> {

        /**
         * 批量保存数据，即id存在则更新，不存在则插入
         *
         * @param entities
         * @param <E>
         *            数据集
         * @return
         */
        List<T> batchSaveOrUpdate(List<T> entities);

        /**
         * 保存数据，即id存在则更新，不存在则插入
         *
         * @param entities
         * @param <E>
         *            数据集
         * @return
         */
        T saveOrUpdate(T entities);

        /**
         * 批量删除对象
         *
         * @param entities
         *            需要删除的对象
         * @return
         */
        public List<T> batchRemove(List<T> entities);

        /**
         * 批量删除对象
         *
         * @param entities
         *            需要删除的对象id
         * @return
         */
        public List<T> batchRemove(Serializable[] idSet);

        /**
         * 删除对象
         *
         * @param entity
         *            需要删除的对象
         * @return
         */
        public T remove(T entity);

        /**
         * 删除对象
         *
         * @param id
         *            需要删除的对象id
         * @return
         */
        public T remove(Serializable id);

        /**
         * 根据主键查询id
         *
         * @param id
         *            主键
         * @return
         */
        T findByPrimaryKey(Serializable id);

        /**
         * 根据条件查询结果
         *
         * @param condition
         *            条件
         * @return
         */
        <E extends T> T findByCondition(E condition);

        /**
         * 根据给定条件查询数据
         *
         * @param condition
         * @param <E>
         * @return
         */
        <E extends T> List<T> findList(E condition);

        /**
         * 根据给定条件查询结果，结果有序
         *
         * @author Zhang Kangkang
         * @version 1.0.0
         */
        <E extends T> List<T> findList(E condition, SortChain sort);

        /**
         * 查询结果，结果有序
         *
         * @author Zhang Kangkang
         * @version 1.0.0
         */
        List<T> findList(SortChain sort);

        /**
         * 根据id查询结果集内容，sql: id in(data)
         * 
         * @param data
         * @return
         */
        List<T> findIn(Serializable[] data);

        /**
         * 根据id查询结果集内容，sql: id in(data)
         * 
         * @param data
         * @return
         */
        List<T> findIn(Collection<? extends Serializable> data);

        /**
         * 查询结果集内容，sql: field in(data)
         * 
         * @param field
         * @param data
         * @return
         */
        List<T> findIn(QueryFunction<T> field, Collection<Serializable> data);

        /**
         * 根据给定的分页条件查询结果
         *
         *
         * @param page
         *            分页参数
         * @return
         */
        Page<T> findPage(Page<T> page);

        /**
         * 根据给定的分页条件和查询条件查询结果
         *
         *
         * @param page
         *            分页参数
         * @param condition
         *            查询条件
         * @return
         */
        <E extends T> Page<T> findPage(Page<T> page, E condition);

        /**
         * 根据给定的分页条件、查询条件和排序队列查询结果
         *
         *
         * @param page
         *            分页参数
         * @param condition
         *            查询条件
         * @param sort
         *            排序队列
         * @return
         */
        <E extends T> Page<T> findPage(Page<T> page, E condition, SortChain sort);

        /**
         * 根据给定的分页条件和排序队列查询结果查询结果
         *
         *
         * @param page
         *            分页参数
         * @param sort
         *            排序队列
         * @return
         */
        Page<T> findPage(Page<T> page, SortChain sort);

        /**
         * 新建一个条件构造器
         * 
         * @return
         */
        public QueryBuilder<T> newQuery();

        /**
         * 根据自定条件构造器查询总条数
         * 
         * @param query
         * @return 条数
         */
        public Long count(QueryBuilder<T> query);

        /**
         * 根据自定条件构造器查询列表
         * 
         * @param query
         * @return 列表
         */
        public List<T> findList(QueryBuilder<T> query);

        /**
         * 根据自定条件构造器查询列表
         * 
         * @param query
         * @return 单个结果
         */
        public T findOne(QueryBuilder<T> query);

        /**
         * 根据自定条件构造器查询列表
         * 
         * @param query
         * @return 分页结果
         */
        public Page<T> findPage(Page<T> page, QueryBuilder<T> query);

        /**
         * 根据自定条件构造器查询列表
         * 
         * @param query
         * @return 列表
         */
        public <E extends T> List<E> findList(Class<E> cls, QueryBuilder<T> query);

        /**
         * 根据自定条件构造器查询列表
         * 
         * @param query
         * @return 单个结果
         */
        public <E extends T> E findOne(Class<E> cls, QueryBuilder<T> query);

        /**
         * 根据自定条件构造器查询列表
         * 
         * @param query
         * @return 分页结果
         */
        public <E extends T> Page<E> findPage(Page<E> page, Class<E> cls, QueryBuilder<T> query);

        /**
         * 根据自定条件构造器查询列表
         * 
         * @param query
         * @return 列表
         */
        public List<Map<String, Object>> findListToMap(QueryBuilder<T> query);

        /**
         * 根据自定条件构造器查询列表
         * 
         * @param query
         * @return 单个结果
         */
        public Map<String, Object> findOneToMap(QueryBuilder<T> query);

        /**
         * 根据自定条件构造器查询列表
         * 
         * @param query
         * @return 分页结果
         */
        public Page<Map<String, Object>> findPageToMap(Page<Map<String, Object>> page, QueryBuilder<T> query);

        /**
         * 获取实体类信息
         * 
         * @return 类信息
         */
        public Class<T> getMainClass();

        /**
         * 执行自定义语句
         * 
         * @return 单个数据结果
         */
        public T executeOneNamedQuery(String namedQuery, Object[] args, Parameter[] parameter);

        /**
         * 执行自定义语句
         * 
         * @return 单个数据结果
         */
        public List<T> executeListNamedQuery(String namedQuery, Object[] args, Parameter[] parameter);

        /**
         * 执行自定义语句
         * 
         * @return 单个数据结果
         */
        public Page<T> executePageNamedQuery(String namedQuery, Object[] args, Parameter[] parameter);

    }

    /**
     * 分页构造
     *
     * @author Zhang Kangkang
     * @version 1.0.0
     */
    public static class Page<T> implements Serializable {

        private static final long serialVersionUID = 1L;

        private List<T> entities;

        private Integer pageSize = 10;

        private Integer pageNumber = 1;

        private Integer count;

        private Integer pages;

        private Boolean isFirst = true;

        private Boolean isLast = false;

        private List<String> descs;

        private List<String> ascs;

        public List<T> getEntities() {
            return entities;
        }

        public void setEntities(List<T> entities) {
            this.entities = entities;
        }

        public Integer getPageSize() {
            return pageSize;
        }

        public void setPageSize(Integer pageSize) {
            this.pageSize = pageSize;
        }

        public Integer getPageNumber() {
            return pageNumber;
        }

        public void setPageNumber(Integer pageNumber) {
            this.pageNumber = pageNumber;
        }

        public Integer getCount() {
            return count;
        }

        public void setCount(Long count) {
            this.count = count.intValue();
            this.pages = this.count.intValue() % this.pageSize == 0 ? this.count.intValue() / this.pageSize
                : this.count.intValue() / this.pageSize + 1;
            this.isFirst = this.pageNumber == 1;
            this.isLast = this.pageNumber >= this.pages;
        }

        public Integer getPages() {
            return pages;
        }

        public void setPages(Integer pages) {
            this.pages = pages;
        }

        public Boolean getIsFirst() {
            return isFirst;
        }

        public void setIsFirst(Boolean isFirst) {
            this.isFirst = isFirst;
        }

        public Boolean getIsLast() {
            return isLast;
        }

        public void setIsLast(Boolean isLast) {
            this.isLast = isLast;
        }

        public List<String> getDescs() {
            return descs;
        }

        public void setDescs(List<String> descs) {
            this.descs = descs;
        }

        public List<String> getAscs() {
            return ascs;
        }

        public void setAscs(List<String> ascs) {
            this.ascs = ascs;
        }

        public static <T> Page<T> newInstance(Integer pageNumber, Integer pageSize) {
            Page<T> page = new Page<T>();
            page.setPageNumber(pageNumber);
            page.setPageSize(pageSize);
            return page;
        }

        public static <T> Page<T> newInstance() {
            return new Page<T>();
        }

    }

    /**
     * 过滤模式
     * 
     * @author Zhang Kangkang
     */
    public enum FilterMode {

        /**
         * 查询所有参数
         */
        ALL,

        /**
         * 只查询输入参数
         */
        INCLUDE,

        /**
         * 过滤输入参数
         */
        EXCLUDE,

        /**
         * 不过滤
         */
        NONE;

    }

    /**
     * Twitter_Snowflake<br>
     * SnowFlake的结构如下(每部分用-分开):<br>
     * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
     * 1位标识，由于long基本类型在Java中是带符号的，最高位是符号位，正数是0，负数是1，所以id一般是正数，最高位是0<br>
     * 41位时间截(毫秒级)，注意，41位时间截不是存储当前时间的时间截，而是存储时间截的差值（当前时间截 - 开始时间截)
     * 得到的值），这里的的开始时间截，一般是我们的id生成器开始使用的时间，由我们程序来指定的（如下下面程序IdWorker类的startTime属性）。41位的时间截，可以使用69年，年T = (1L << 41) /
     * (1000L * 60 * 60 * 24 * 365) = 69<br>
     * 10位的数据机器位，可以部署在1024个节点，包括5位datacenterId和5位workerId<br>
     * 12位序列，毫秒内的计数，12位的计数顺序号支持每个节点每毫秒(同一机器，同一时间截)产生4096个ID序号<br>
     * 加起来刚好64位，为一个Long型。<br>
     * SnowFlake的优点是，整体上按照时间自增排序，并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分)，并且效率较高，经测试，SnowFlake每秒能够产生26万ID左右。
     * 
     * 需注意：依赖机器时间，如果发生回拨会导致可能生成id重复
     * 
     * @author Zhang Kangkang
     * @version 1.0.0
     */
    public static class SnowflakeIdWorker {

        /**
         * 开始时间截 (2015-01-01)
         */
        private final long twepoch = 1546272000000L;

        /**
         * 机器id所占的位数
         */
        private final long workerIdBits = 5L;

        /**
         * 数据标识id所占的位数
         */
        private final long datacenterIdBits = 5L;

        /**
         * 支持的最大机器id，结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数)
         */
        private final long maxWorkerId = -1L ^ (-1L << workerIdBits);

        /**
         * 支持的最大数据标识id，结果是31
         */
        private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);

        /**
         * 序列在id中占的位数
         */
        private final long sequenceBits = 12L;

        /**
         * 机器ID向左移12位
         */
        private final long workerIdShift = sequenceBits;

        /**
         * 数据标识id向左移17位(12+5)
         */
        private final long datacenterIdShift = sequenceBits + workerIdBits;

        /**
         * 时间截向左移22位(5+5+12)
         */
        private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;

        /**
         * 生成序列的掩码，这里为4095 (0b111111111111=0xfff=4095)
         */
        private final long sequenceMask = -1L ^ (-1L << sequenceBits);

        /**
         * 工作机器ID(0~31)
         */
        private long workerId;

        /**
         * 数据中心ID(0~31)
         */
        private long datacenterId;

        /**
         * 毫秒内序列(0~4095)
         */
        private long sequence = 0L;

        /**
         * 上次生成ID的时间截
         */
        private long lastTimestamp = -1L;

        /**
         * 构造函数
         * 
         * @param workerId
         *            工作ID (0~31)
         * @param datacenterId
         *            数据中心ID (0~31)
         */
        public SnowflakeIdWorker(long workerId, long datacenterId) {
            if (workerId > maxWorkerId || workerId < 0) {
                throw new IllegalArgumentException(
                    String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
            }
            if (datacenterId > maxDatacenterId || datacenterId < 0) {
                throw new IllegalArgumentException(
                    String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
            }
            this.workerId = workerId;
            this.datacenterId = datacenterId;
        }

        /**
         * 获得下一个ID (该方法是线程安全的)
         * 
         * @return SnowflakeId
         */
        public synchronized long nextId() {
            long timestamp = timeGen();

            // 如果当前时间小于上一次ID生成的时间戳，说明系统时钟回退过这个时候应当抛出异常
            if (timestamp < lastTimestamp) {
                throw new RuntimeException(String.format(
                    "Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
            }

            // 如果是同一时间生成的，则进行毫秒内序列
            if (lastTimestamp == timestamp) {
                sequence = (sequence + 1) & sequenceMask;
                // 毫秒内序列溢出
                if (sequence == 0) {
                    // 阻塞到下一个毫秒,获得新的时间戳
                    timestamp = tilNextMillis(lastTimestamp);
                }
            }
            // 时间戳改变，毫秒内序列重置
            else {
                sequence = 0L;
            }

            // 上次生成ID的时间截
            lastTimestamp = timestamp;

            // 移位并通过或运算拼到一起组成64位的ID
            return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift)
                | (workerId << workerIdShift) | sequence;
        }

        /**
         * 阻塞到下一个毫秒，直到获得新的时间戳
         * 
         * @param lastTimestamp
         *            上次生成ID的时间截
         * @return 当前时间戳
         */
        protected long tilNextMillis(long lastTimestamp) {
            long timestamp = timeGen();
            while (timestamp <= lastTimestamp) {
                timestamp = timeGen();
            }
            return timestamp;
        }

        /**
         * 返回以毫秒为单位的当前时间
         * 
         * @return 当前时间(毫秒)
         */
        protected long timeGen() {
            return System.currentTimeMillis();
        }

    }

    /**
     * 反射辅助工具
     *
     * @author Zhang Kangkang
     * @version 1.0.0
     */
    public static final class ReflectUtils {

        public static final String GETTER_NAME = "get";

        public static final String SETTER_NAME = "set";

        private static Map<Class<?>, Set<String>> CACHED_COLUMNS = new HashMap<>();

        private ReflectUtils() {}

        public static String getGetterName(String fieldName) {
            return GETTER_NAME + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
        }

        public static String getGetterName(Method method) {
            return method.getName().replace(GETTER_NAME, "").substring(0, 1).toLowerCase()
                + method.getName().substring(4);
        }

        public static String getSetterName(String fieldName) {
            return SETTER_NAME + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
        }

        public static Set<String> getColumns(Class<?> cls) {

            if (CACHED_COLUMNS.get(cls) != null) {
                return CACHED_COLUMNS.get(cls);
            }

            Field[] declaredFields = cls.getDeclaredFields();
            Set<String> columns = new HashSet<>(declaredFields.length);

            for (Field declaredField : declaredFields) {
                Column column = declaredField.getAnnotation(Column.class);
                if (column != null) {
                    columns.add(declaredField.getName());
                }
            }
            CACHED_COLUMNS.put(cls, columns);
            return CACHED_COLUMNS.get(cls);

        }

        public static <T> Object getId(T t) {
            Class<?> cls = t.getClass();
            Field[] fields = cls.getDeclaredFields();
            for (Field field : fields) {
                if (field.getAnnotation(Id.class) != null) {
                    field.setAccessible(true);
                    try {
                        return field.get(t);
                    } catch (Exception e) {
                        e.printStackTrace();
                        return null;
                    }
                }
            }
            return null;
        }

        public static <T> String getIdName(Class<T> cls) {
            Field[] fields = cls.getDeclaredFields();
            for (Field field : fields) {
                if (field.getAnnotation(Id.class) != null) {
                    try {
                        return field.getName();
                    } catch (Exception e) {
                        e.printStackTrace();
                        return null;
                    }
                }
            }
            return null;
        }

        public static Set<Method> getAllGetterMethod(Class<?> cls) {

            Set<Method> methodSet = new HashSet<>();
            if (cls == Object.class) {
                return methodSet;
            }

            Method[] methods = cls.getMethods();
            for (Method method : methods) {
                if (method.getName().startsWith(GETTER_NAME) && method.getParameterCount() == 0
                    && !"getClass".equals(method.getName())) {
                    methodSet.add(method);
                }
            }
            return methodSet;
        }

    }

    /**
     * 实体类工具
     *
     * @author Zhang Kangkang
     * @version 1.0.0
     */
    public static final class EntityBuilder {

        private static final SnowflakeIdWorker snowflakeIdWorker = new SnowflakeIdWorker(1L, 1L);

        private EntityBuilder() {}

        /**
         * 获得一个实体对象，补充注解为@Column切nullable=false的默认值
         * 
         * @author Zhang Kangkang
         * 
         * @param cls
         *            对象的Class对象
         * @return 默认属性的实例对象
         */
        public static <T> T get(Class<T> cls) {
            return get(cls, null);
        }

        /**
         * 填充一个实体对象属性注解为@Column切nullable=false的默认值
         * 
         * @author Zhang Kangkang
         * @param exist
         *            需要填充的对象
         * @return 默认属性的实例对象
         */
        public static <T> T fill(T exist) {
            return get(null, exist);
        }

        /**
         * 合并两对象属性
         * 
         * @author Zhang Kangkang
         * @param main
         *            需要赋值的对象
         * @param merged
         *            需要被合并的对象
         * @return
         */
        public static <T> T merge(T main, T merged) {
            try {

                Field[] declaredFields = main.getClass().getDeclaredFields();
                for (Field declaredField : declaredFields) {
                    declaredField.setAccessible(true);
                    Column columnAnnotation = declaredField.getAnnotation(Column.class);
                    if (columnAnnotation != null && declaredField.get(merged) != null) {
                        declaredField.set(main, declaredField.get(merged));
                    }
                }
                return main;
            } catch (Exception e) {
                throw new TedException("填充的对象属性失败", ExceptionCode.BUSINESS_ERROR);
            }
        }

        /**
         * 获取一个长度在17-19之间的长整数对象，一般用于生成数据库主键
         * 
         * @author Zhang Kangkang
         * 
         * @return Longd对象
         */
        public static Long getId() {
            return snowflakeIdWorker.nextId();
        }

        private static <T> T get(Class<T> cls, T exist) {
            try {

                T instance = exist != null ? exist : cls.newInstance();
                if (instance == null) {
                    throw new TedException("填充的对象不为空", ExceptionCode.BUSINESS_ERROR);
                }
                Field[] declaredFields = instance.getClass().getDeclaredFields();
                for (Field declaredField : declaredFields) {
                    declaredField.setAccessible(true);
                    Column column = declaredField.getAnnotation(Column.class);
                    if (column != null && !column.nullable() && declaredField.get(instance) == null) {
                        Class<?> type = declaredField.getType();
                        if (type == Long.class) {
                            declaredField.set(instance, getId());
                            continue;
                        }
                        if (type == Integer.class) {
                            declaredField.set(instance, 0);
                            continue;
                        }
                        if (type == String.class) {
                            declaredField.set(instance, "");
                            continue;
                        }
                        if (type == LocalDateTime.class) {
                            declaredField.set(instance, LocalDateTime.now());
                            continue;
                        }
                        if (type == BigDecimal.class) {
                            declaredField.set(instance, BigDecimal.ZERO);
                            continue;
                        }
                        if (type == Boolean.class) {
                            declaredField.set(instance, Boolean.FALSE);
                            continue;
                        }
                    }
                }
                return instance;
            } catch (Exception e) {
                throw new TedException("填充的对象属性失败", ExceptionCode.BUSINESS_ERROR);
            }
        }

    }

    /**
     * 集合操作工具
     *
     * @author Zhang Kangkang
     * @version 1.0.0
     */
    public static final class CollectionUtils {

        private CollectionUtils() {}

        /**
         * 列表转Set集合
         * 
         * @param iterable
         *            列表
         * @param function
         *            需要转换的属性
         * @return set
         * @author Zhang Kangkang
         */
        public static <V, E> Set<V> list2Set(List<E> iterable, Function<? super E, ? extends V> function) {
            return iterable.stream().map(function).collect(Collectors.toSet());
        }

        /**
         * 数组转Set集合
         * 
         * @param array
         *            数组
         * @return set
         * @author Zhang Kangkang
         */
        public static <T> Set<T> array2Set(T[] array) {
            return Stream.of(array).collect(Collectors.toSet());
        }

        /**
         * 数组转Set集合
         * 
         * @param array
         *            数组
         * @return set
         * @author Zhang Kangkang
         */
        public static <T> Set<T> array2Set(T obj) {
            return Stream.of(obj).collect(Collectors.toSet());
        }

    }

}
